﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using RedBit.UserVoice.Model;
using Hammock;
using Newtonsoft.Json.Linq;
using System.Linq;
using Hammock.Web;
using Hammock.Authentication.OAuth;
using RedBit.UserVoice.Helpers;

namespace RedBit.UserVoice.Services
{
    public class UVSuggestionService : BaseUVApi
    {

        #region Get Single Suggestion
        public static void GetSingleSuggestion(string forumId, string suggestionId, Action<UVResponse<UVSuggestion>> handler)
        {
            var client = new RestClient
            {
                Authority = string.Format(UserVoiceConstants.URL_TEMPLATE, UserVoiceAPI.AppName),
            };

            var request = new RestRequest
            {
                Path = string.Format(UserVoiceConstants.GET_SINGLE_SUGGESTION_SUFFIX, forumId, suggestionId)
            };

            request.AddParameter("client", UserVoiceAPI.Key);

            client.BeginRequest(request, HandleGetSingleSuggestionResponse, handler);
        }

        private static void HandleGetSingleSuggestionResponse(RestRequest rq, RestResponse rs, object token)
        {
            var response = JObject.Parse(rs.Content);
            var obj = response["suggestion"];

            var error = ParseError(response);
            var suggestion = ParseSuggestion(obj);

            var handler = token as Action<UVResponse<UVSuggestion>>;

            var resp = new UVResponse<UVSuggestion>()
            {
                Error = error,
                Model = suggestion
            };
            handler(resp);
        }
        #endregion Get Single Suggestion

        #region Get Suggestions for Forum
        public static void GetSuggestionsForForum(string forumId, Action<UVResponse<ICollection<UVSuggestion>>> handler)
        {
            GetSuggestionsForForum(forumId, UVSuggestionFilter.Published, UVSuggestionSort.Votes, handler);
        }

        public static void GetSuggestionsForForum(string forumId, UVSuggestionFilter filter, Action<UVResponse<ICollection<UVSuggestion>>> handler)
        {
            GetSuggestionsForForum(forumId, filter, UVSuggestionSort.Votes, handler);
        }

        public static void GetSuggestionsForForum(string forumId, UVSuggestionSort sort, Action<UVResponse<ICollection<UVSuggestion>>> handler)
        {
            GetSuggestionsForForum(forumId, UVSuggestionFilter.All, sort, handler);
        }

        public static void GetSuggestionsForForum(string forumId, UVSuggestionFilter filter, UVSuggestionSort sort, Action<UVResponse<ICollection<UVSuggestion>>> handler)
        {
            GetSuggestionsForForum(forumId, filter, sort, 1, handler);
        }

        public static void GetSuggestionsForForum(string forumId, UVSuggestionFilter filter, UVSuggestionSort sort, int page, Action<UVResponse<ICollection<UVSuggestion>>> handler)
        {
            var client = new RestClient
            {
                Authority = string.Format(UserVoiceConstants.URL_TEMPLATE, UserVoiceAPI.AppName),
            };

            var request = new RestRequest
            {
                Path = string.Format( UserVoiceConstants.GET_SUGGESTIONS_SUFFIX, forumId)
            };

            request.AddParameter("client", UserVoiceAPI.Key);
            request.AddParameter("page", page.ToString());
            //TODO: Uncomment next line once we figure out what's going on with license for filters
           // request.AddParameter("filter", filter.ToString("g").ToLower());
            request.AddParameter("sort", sort.ToString("g").ToLower());

            client.BeginRequest(request, HandleGetSuggestionsResponse, handler);
        }

        private static void HandleGetSuggestionsResponse(RestRequest rq, RestResponse rs, object token)
        {
            
            var response = JObject.Parse(rs.Content);
            var error = ParseError(response);
            var jsonObjects = response["suggestions"] as JArray;

            var suggestions =
                from obj in jsonObjects
                select ParseSuggestion(obj);


            var handler = token as Action<UVResponse<ICollection<UVSuggestion>>>;

            var resp = new UVResponse<ICollection<UVSuggestion>>() { Model = suggestions.ToList(), Error = error };
            handler(resp);
        }

        

        private static UVSuggestion ParseSuggestion(JToken obj)
        {
            if (obj == null) return null;
            return new UVSuggestion
            {
                Id = obj["id"].Value<int>(),
                Title = obj["title"].Value<string>(),
                CreatedAt = obj["created_at"].Value<DateTime>(),
                Text = obj["text"].Value<string>(),
                Category = !obj["category"].HasValues ? "" : obj["category"]["name"].Value<string>(),
                CommentCount = obj["comments_count"].Value<int>(),
                VoteCount = obj["vote_count"].Value<int>(),
                Status = !obj["status"].HasValues ? "new" : obj["status"]["name"].Value<string>(),
                ForumId = obj["topic"]["forum"]["id"].Value<string>()
            };
        }
        #endregion Get Suggestions for Forum

        #region Get Suggestions for User
        
        public static void GetSuggestionsForUser(string forumId, int page, Action<UVResponse<ICollection<UVSuggestion>>> handler)
        {
            var client = new RestClient
            {
                Authority = string.Format(UserVoiceConstants.URL_TEMPLATE, UserVoiceAPI.AppName),
            };

            var request = new RestRequest
            {
                Path = string.Format(UserVoiceConstants.GET_USER_SUGGESTIONS_SUFFIX, forumId, UVUserHelper.CurrentUser.Id)
            };

            request.AddParameter("client", UserVoiceAPI.Key);
            request.AddParameter("page", page.ToString());
            request.AddParameter("rnd", DateTime.Now.Ticks.ToString());

            client.BeginRequest(request, HandleGetUserSuggestionsResponse, handler);
        }

        private static void HandleGetUserSuggestionsResponse(RestRequest rq, RestResponse rs, object token)
        {

            var response = JObject.Parse(rs.Content);
            var error = ParseError(response);
            var jsonObjects = response["suggestions"] as JArray;

            var suggestions =
                from obj in jsonObjects
                select ParseSuggestion(obj);


            var handler = token as Action<UVResponse<ICollection<UVSuggestion>>>;

            var resp = new UVResponse<ICollection<UVSuggestion>>() { Model = suggestions.ToList(), Error = error };
            handler(resp);
        }

        #endregion Get Suggestions for User

        #region Search Suggestions for Forum
        public static void SearchSuggestionsForForum(string query, string forumId, Action<UVResponse<ICollection<UVSuggestion>>> handler)
        {
            var client = new RestClient
            {
                Authority = string.Format(UserVoiceConstants.URL_TEMPLATE, UserVoiceAPI.AppName),
            };

            var request = new RestRequest
            {
                Path = string.Format(UserVoiceConstants.SEARCH_SUGGESTIONS_SUFFIX, forumId)
            };

            request.AddParameter("client", UserVoiceAPI.Key);
            request.AddParameter("query", query);

            client.BeginRequest(request, HandleSearchSuggestionsResponse, handler);
        }

        private static void HandleSearchSuggestionsResponse(RestRequest rq, RestResponse rs, object token)
        {
            var response = JObject.Parse(rs.Content);
            var jsonObjects = response["suggestions"] as JArray;
            var error = ParseError(response);

            var suggestions =
                from obj in jsonObjects
                select ParseSuggestion(obj);

            var handler = token as Action<UVResponse<ICollection<UVSuggestion>>>;


            var resp = new UVResponse<ICollection<UVSuggestion>>()
            {
                Error = error,
                Model = suggestions.ToList()
            };

            handler(resp);
        }
        #endregion Search Suggestions for Forum

        #region Create Suggestion
        public static void CreateSuggestion(UVSuggestion suggestion, Action<UVResponse<UVSuggestion>> responseHandler)
        {
            //// Create Credentials
            var credentials = BuildCredentials();

            credentials.Token = UserVoiceAPI.AccessToken.Key;
            credentials.TokenSecret = UserVoiceAPI.AccessToken.Secret;


            var client = new RestClient
            {
                Authority = string.Format(UserVoiceConstants.URL_TEMPLATE, UserVoiceAPI.AppName),
                Credentials = credentials,
                Method = WebMethod.Post
            };

            var request = new RestRequest
            {
                Path = string.Format(UserVoiceConstants.CREATE_SUGGESTION_SUFFIX_TEMPLATE, suggestion.ForumId),
            };

            
            if( !string.IsNullOrEmpty( suggestion.Text.Trim() ) )
               request.AddParameter("suggestion%5Btext%5D", suggestion.Text);
            request.AddParameter("suggestion%5Btitle%5D", suggestion.Title);
            request.AddParameter("suggestion%5Bvotes%5D", suggestion.VoteCount.ToString());
            //request.AddParameter("oauth_token", UserVoiceAPI.AccessToken.Key);


            client.BeginRequest(request, HandleCreateSuggestion, responseHandler);
        }


        private static void HandleCreateSuggestion(RestRequest rq, RestResponse rs, object token)
        {
            //TODO: Handle Errors
            var handler = token as Action<UVResponse<UVSuggestion>>;

            var response = JObject.Parse(rs.Content);

            var obj = response["suggestion"];
            var error = ParseError(response);

            var suggestion = ParseSuggestion(obj);
            var resp = new UVResponse<UVSuggestion>()
            {
                Error = error,
                Model = suggestion
            };
            handler(resp);
        }
        #endregion Create Suggestion

        #region Vote On Suggestion
        public static void VoteOnSuggestion(string forumId, int suggestionId, int voteCount, Action<UVResponse<UVSuggestion>> responseHandler)
        {
            //// Create Credentials
            var credentials = BuildCredentials();

            credentials.Token = UserVoiceAPI.AccessToken.Key;
            credentials.TokenSecret = UserVoiceAPI.AccessToken.Secret;


            var client = new RestClient
            {
                Authority = string.Format(UserVoiceConstants.URL_TEMPLATE, UserVoiceAPI.AppName),
                Credentials = credentials,
                Method = WebMethod.Post
            };

            var request = new RestRequest
            {
                Path = string.Format(UserVoiceConstants.VOTE_ON_SUGGESTION_SUFFIX, forumId, suggestionId ),
            };

            request.AddParameter("to", voteCount.ToString());

            client.BeginRequest(request, HandleVoteOnSuggestion, responseHandler);
        }


        private static void HandleVoteOnSuggestion(RestRequest rq, RestResponse rs, object token)
        {
            //TODO: Handle Errors
            var handler = token as Action<UVResponse<UVSuggestion>>;
            var response = JObject.Parse(rs.Content);

            var obj = response["suggestion"];

            var suggestion = ParseSuggestion(obj);
            var error = ParseError(response);

            handler(new UVResponse<UVSuggestion> { Model = suggestion, Error = error });
        }
        #endregion Vote On Suggestion
    }
}
